{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "17966a4b",
   "metadata": {},
   "outputs": [],
   "source": [
    "##\n",
    "#让解释器支持多个数字加减法表达式的解释"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "f2f1554f",
   "metadata": {},
   "outputs": [],
   "source": [
    "INTEGER, PLUS, MINUS, EOF = 'INTERGER', 'PLUS', 'MINUS', 'EOF'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "45fb3e98",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Token:\n",
    "    \"\"\"记号类\n",
    "    \"\"\"\n",
    "    def __init__(self, value_type, value):\n",
    "        self.value_type = value_type # 记号的类型\n",
    "        self.value = value # 记号的值\n",
    "    \n",
    "    def __str__(self):\n",
    "        \"\"\"重写查看记号内容的方法\"\"\"\n",
    "        return f\"Token({self.value_type}, {self.value})\"\n",
    "    \n",
    "    def __repr__(self):\n",
    "        return self.__str__()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "792d0769",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Interpreter:\n",
    "    \"\"\"解释器类\n",
    "    \"\"\"\n",
    "    def __init__(self, text):\n",
    "        self.text = text\n",
    "        self.position = 0\n",
    "        self.current_token = None\n",
    "        self.current_char = self.text[self.position]\n",
    "    \n",
    "    def error(self):\n",
    "        raise Exception('警告：错误的输入内容！')\n",
    "    \n",
    "    def advance(self):\n",
    "        \"\"\"定义获取下一个字符的方法\n",
    "        \"\"\"\n",
    "        self.position += 1\n",
    "        if self.position >= len(self.text):\n",
    "            self.current_char = None\n",
    "        else:\n",
    "            self.current_char = self.text[self.position]\n",
    "    \n",
    "    def skip_whitespace(self):\n",
    "        \"\"\"定义跳过空格的方法\n",
    "        \"\"\"\n",
    "        while self.current_char is not None and self.current_char.isspace():\n",
    "            self.advance()\n",
    "    \n",
    "    def long_integer(self):\n",
    "        result = ''\n",
    "        while self.current_char is not None and self.current_char.isdigit():\n",
    "            result += self.current_char\n",
    "            self.advance()\n",
    "        return int(result)\n",
    "            \n",
    "    def get_next_token(self):\n",
    "        while self.current_char is not None:\n",
    "            if self.current_char.isspace():\n",
    "                self.skip_whitespace()\n",
    "                continue\n",
    "            if self.current_char.isdigit():\n",
    "                token = Token(INTEGER, self.long_integer())\n",
    "                return token\n",
    "            if self.current_char == '+':\n",
    "                token = Token(PLUS, self.current_char)\n",
    "                self.advance()\n",
    "                return token\n",
    "            if self.current_char == '-':\n",
    "                token = Token(MINUS, self.current_char)\n",
    "                self.advance()\n",
    "                return token\n",
    "            self.error()\n",
    "        return Token(EOF, None)\n",
    "    \n",
    "    def eat(self, token_type):\n",
    "        print(self.current_token)\n",
    "        if self.current_token.value_type == token_type:\n",
    "            if token_type != EOF:\n",
    "                self.current_token = self.get_next_token()\n",
    "        else:\n",
    "            self.error()\n",
    "    \n",
    "    def term(self):\n",
    "        token = self.current_token\n",
    "        self.eat(INTEGER)\n",
    "        return token.value\n",
    "    \n",
    "    def expr(self):\n",
    "        self.current_token = self.get_next_token()\n",
    "        result = self.term()\n",
    "        \n",
    "        while self.current_token.value_type in (PLUS, MINUS):\n",
    "            if self.current_token.value_type == PLUS:\n",
    "                self.eat(PLUS)\n",
    "                result += self.term()\n",
    "            if self.current_token.value_type == MINUS:\n",
    "                self.eat(MINUS)\n",
    "                result -= self.term()\n",
    "        return result\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d6bb9be0",
   "metadata": {},
   "outputs": [],
   "source": [
    "def main():\n",
    "    while True:\n",
    "        text = input(\"输入算式：\")\n",
    "        if text == 'q':\n",
    "            break\n",
    "        interpreter = Interpreter(text)\n",
    "        result = interpreter.expr()\n",
    "        print(text, \"=\", result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "13d63f4e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "输入算式：1+2-3\n",
      "Token(INTERGER, 1)\n",
      "Token(PLUS, +)\n",
      "Token(INTERGER, 2)\n",
      "Token(MINUS, -)\n",
      "Token(INTERGER, 3)\n",
      "1+2-3 = 0\n",
      "输入算式：1 + 2 +\n",
      "Token(INTERGER, 1)\n",
      "Token(PLUS, +)\n",
      "Token(INTERGER, 2)\n",
      "Token(PLUS, +)\n",
      "Token(EOF, None)\n"
     ]
    },
    {
     "ename": "Exception",
     "evalue": "警告：错误的输入内容！",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mException\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [6]\u001b[0m, in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mmain\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
      "Input \u001b[1;32mIn [5]\u001b[0m, in \u001b[0;36mmain\u001b[1;34m()\u001b[0m\n\u001b[0;32m      5\u001b[0m     \u001b[38;5;28;01mbreak\u001b[39;00m\n\u001b[0;32m      6\u001b[0m interpreter \u001b[38;5;241m=\u001b[39m Interpreter(text)\n\u001b[1;32m----> 7\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43minterpreter\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mexpr\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m      8\u001b[0m \u001b[38;5;28mprint\u001b[39m(text, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m=\u001b[39m\u001b[38;5;124m\"\u001b[39m, result)\n",
      "Input \u001b[1;32mIn [4]\u001b[0m, in \u001b[0;36mInterpreter.expr\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m     72\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcurrent_token\u001b[38;5;241m.\u001b[39mvalue_type \u001b[38;5;241m==\u001b[39m PLUS:\n\u001b[0;32m     73\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39meat(PLUS)\n\u001b[1;32m---> 74\u001b[0m     result \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mterm\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m     75\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcurrent_token\u001b[38;5;241m.\u001b[39mvalue_type \u001b[38;5;241m==\u001b[39m MINUS:\n\u001b[0;32m     76\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39meat(MINUS)\n",
      "Input \u001b[1;32mIn [4]\u001b[0m, in \u001b[0;36mInterpreter.term\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m     62\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mterm\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[0;32m     63\u001b[0m     token \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcurrent_token\n\u001b[1;32m---> 64\u001b[0m     \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43meat\u001b[49m\u001b[43m(\u001b[49m\u001b[43mINTEGER\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m     65\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m token\u001b[38;5;241m.\u001b[39mvalue\n",
      "Input \u001b[1;32mIn [4]\u001b[0m, in \u001b[0;36mInterpreter.eat\u001b[1;34m(self, token_type)\u001b[0m\n\u001b[0;32m     58\u001b[0m         \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcurrent_token \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mget_next_token()\n\u001b[0;32m     59\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m---> 60\u001b[0m     \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43merror\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
      "Input \u001b[1;32mIn [4]\u001b[0m, in \u001b[0;36mInterpreter.error\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m     10\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21merror\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m---> 11\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m警告：错误的输入内容！\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
      "\u001b[1;31mException\u001b[0m: 警告：错误的输入内容！"
     ]
    }
   ],
   "source": [
    "main()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
